package com.cxz.study.domain.order;

import com.cxz.study.domain.exception.OrderNotCancelableException;
import com.cxz.study.domain.exception.OrderNotFoundException;
import com.cxz.study.domain.exception.PermissionDeniedException;
import com.cxz.study.domain.order.command.CancelOrderCommand;
import com.cxz.study.domain.order.command.CreateOrderCommand;
import com.cxz.study.domain.order.command.FindOrderCommand;
import com.cxz.study.domain.order.event.OrderCancelledEvent;
import com.cxz.study.domain.order.event.OrderCreatedEvent;
import com.cxz.study.domain.order.orderId.OrderId;
import com.cxz.study.domain.order.service.InventoryService;
import com.cxz.study.domain.util.Asserts;
import com.cxz.study.loggerApi.BizLog;
import com.cxz.study.loggerApi.BizLogger;
import lombok.RequiredArgsConstructor;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @className: OrderDomainService
 * @author: ocxz1
 * @date: 2025/6/13 下午6:49
 * @Version: 1.0
 * @description: ddd-struct3
 */
@RequiredArgsConstructor
public class OrderDomainService {

    @BizLog
    private final BizLogger logger;
    private final OrderRepository orderRepository;
    private final OrderEventPublisher eventPublisher;
    private final InventoryService inventoryService;

    /**
     * 创建订单
     * @param command 创建订单命令
     * @return 订单
     */
    public Order createOrder(CreateOrderCommand command) {

        logger.info("create order");

        Long productId = command.getProductId();
        Integer productCount = command.getProductCount();

        // 创建订单聚合根
        Order order = new Order(
                OrderId.generate(),
                command.getUserId(),
                command.getProductId(),
                command.getProductCount(),
                LocalDateTime.now(),
                OrderStatus.CREATED
        );

        // 检查订单库存
        order.checkInventory(inventoryService);

        // 扣减库存
        inventoryService.deduct(productId, productCount);

        // 保存订单
        orderRepository.save(order);

        // 发送领域事件
        eventPublisher.publish(new OrderCreatedEvent(order.getId().getValue()));
        return order;
    }

    public Order cancelOrder(CancelOrderCommand command) {
        Order order = orderRepository.findById(command.getOrderId());

        // 验证订单是否存在
        Asserts.isTrue(order != null, OrderNotFoundException.class);

        // 验证用户权限，订单是否属于当前用户
        Asserts.isTrue(Objects.equals(order.getUserId(), command.getUserId()),
                PermissionDeniedException.class);

        // 验证订单状态
        Asserts.isTrue(order.getStatus() == OrderStatus.CREATED, OrderNotCancelableException.class);

        // 恢复库存
        inventoryService.cancelDeduct(order.getProductId(), order.getProductCount());

        // 更新取消订单状态
        Order cancelOrder = order.cancel();
        orderRepository.updateStatus(cancelOrder);

        // 发送领域事件
        eventPublisher.publish(new OrderCancelledEvent(command.getOrderId(), command.getUserId()));
        return cancelOrder;
    }

    public Order findOrder(FindOrderCommand command) {
        return orderRepository.findById(command.getOrderId());
    }
}
